overviewLatencyFirst: "Time to first frame after triggering overview, first time",
overviewFramesFirst: "Frames displayed when going to overview, first time",
overviewLatencySubsequent: "Time to first frame after triggering overview, second time",
- overviewFramesSubsequent: "Frames displayed when going to overview, second time"
+ overviewFramesSubsequent: "Frames displayed when going to overview, second time",
+ usedAfterOverview: "Malloc'ed bytes after the overview is shown once",
+ leakedAfterOverview: "Additional malloc'ed bytes the second time the overview is shown"
};
let METRICS = {
function run() {
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
+ Scripting.defineScriptEvent("afterShowHide", "After a show/hide cycle for the overview");
yield Scripting.sleep(1000);
yield Scripting.waitLeisure();
Main.overview.show();
yield Scripting.waitLeisure();
Scripting.scriptEvent('overviewShowDone');
+
Main.overview.hide();
yield Scripting.waitLeisure();
+
+ global.gc();
+ yield Scripting.sleep(1000);
+ Scripting.collectStatistics();
+ Scripting.scriptEvent('afterShowHide');
}
}
let overviewShowStart;
let overviewFrames;
let overviewLatency;
+let mallocUsedSize = 0;
+let overviewShowCount = 0;
+let firstOverviewUsedSize;
function script_overviewShowStart(time) {
showingOverview = true;
function script_overviewShowDone(time) {
showingOverview = false;
- if (!('overviewLatencyFirst' in METRICS)) {
+ overviewShowCount++;
+
+ if (overviewShowCount == 1) {
METRICS.overviewLatencyFirst = overviewLatency;
METRICS.overviewFramesFirst = overviewFrames;
} else {
}
}
+function script_afterShowHide(time) {
+ if (overviewShowCount == 1) {
+ METRICS.usedAfterOverview = mallocUsedSize;
+ } else {
+ METRICS.leakedAfterOverview = mallocUsedSize - METRICS.usedAfterOverview;
+ }
+}
+
+function malloc_usedSize(time, bytes) {
+ mallocUsedSize = bytes;
+}
+
function clutter_stagePaintDone(time) {
if (showingOverview) {
if (overviewFrames == 0)
Shell.PerfLog.get_default().event("script." + name);
}
+/**
+ * collectStatistics
+ *
+ * Convenience function to trigger statistics collection
+ */
+function collectStatistics() {
+ Shell.PerfLog.get_default().collect_statistics();
+}
+
function _step(g, finish, onError) {
try {
let waitFunction = g.next();
#include <gjs/gjs.h>
#include <girepository.h>
#include <gmodule.h>
+#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include "display.h"
#include "shell-global-private.h"
+#include "shell-perf-log.h"
#include "shell-wm.h"
#include "st.h"
update_font_options (settings);
}
+static void
+malloc_statistics_callback (ShellPerfLog *perf_log,
+ gpointer data)
+{
+ struct mallinfo info = mallinfo ();
+
+ shell_perf_log_update_statistic_i (perf_log,
+ "malloc.arenaSize",
+ info.arena);
+ shell_perf_log_update_statistic_i (perf_log,
+ "malloc.mmapSize",
+ info.hblkhd);
+ shell_perf_log_update_statistic_i (perf_log,
+ "malloc.usedSize",
+ info.uordblks);
+}
+
+static void
+add_statistics (GnomeShellPlugin *shell_plugin)
+{
+ ShellPerfLog *perf_log = shell_perf_log_get_default ();
+
+ /* For probably historical reasons, mallinfo() defines the returned values,
+ * even those in bytes as int, not size_t. We're determined not to use
+ * more than 2G of malloc'ed memory, so are OK with that.
+ */
+ shell_perf_log_define_statistic (perf_log,
+ "malloc.arenaSize",
+ "Amount of memory allocated by malloc() with brk(), in bytes",
+ "i");
+ shell_perf_log_define_statistic (perf_log,
+ "malloc.mmapSize",
+ "Amount of memory allocated by malloc() with mmap(), in bytes",
+ "i");
+ shell_perf_log_define_statistic (perf_log,
+ "malloc.usedSize",
+ "Amount of malloc'ed memory currently in use",
+ "i");
+
+ shell_perf_log_add_statistics_callback (perf_log,
+ malloc_statistics_callback,
+ NULL, NULL);
+}
+
static void
gnome_shell_plugin_start (MutterPlugin *plugin)
{
_shell_global_set_plugin (global, MUTTER_PLUGIN(shell_plugin));
_shell_global_set_gjs_context (global, shell_plugin->gjs_context);
+ add_statistics (shell_plugin);
+
if (!gjs_context_eval (shell_plugin->gjs_context,
"const Main = imports.ui.main; Main.start();",
-1,